package org.example.java.ref;

import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.reflect.Field;

/**
 * Created by Juntao.Zhang on 3/20/15.
 */
public class PhantomReferenceTest {
  static class VeryBig {
    private static final int SIZE = 10000;
    private byte[] la = new byte[1024*1024*50];
    private String ident;

    public VeryBig(String id) {
      ident = id;
    }

    public String toString() {
      return ident;
    }


    protected void finalize() throws Throwable {
      System.out.println("Finalizing " + ident);
      super.finalize();
    }
  }
  public static volatile boolean isRun = true;

  public static void main(String[] args) throws Exception {
    VeryBig abc = new VeryBig("abc");
    System.out.println(abc.getClass() + "@" + abc.hashCode());
    final ReferenceQueue<VeryBig> referenceQueue = new ReferenceQueue<VeryBig>();
    new Thread() {
      public void run() {
        long i = 0;
        while (isRun) {
          i++;
          Object o = referenceQueue.poll();
          if (o != null) {
            try {
              Field rereferent = Reference.class.getDeclaredField("referent");
              rereferent.setAccessible(true);
              Object result = rereferent.get(o);
              System.out.println("gc will collect:"+ result.getClass() + "@"+ result.hashCode());
            } catch (Exception e) {
              e.printStackTrace();
            }
          }
        }
        System.out.println("thread i is "+i);
      }
    }.start();
    PhantomReference<VeryBig> reference = new PhantomReference<VeryBig>(abc,referenceQueue);
    abc = null;

    System.out.println("first gc");
    System.gc();
    Thread.sleep(1000);
    System.out.println(referenceQueue.poll());


    System.out.println("second gc");//reference.clear();
    System.gc();
    Thread.sleep(1000);

    isRun = false;
    reference.clear();

    System.out.println("third gc");
    System.gc();
    System.out.println("fourth gc");
    System.gc();
  }
}
